package com.harsom.camerademo

import android.app.Activity
import android.graphics.Bitmap
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.view.Surface
import com.yuri.xlog.XLog
import java.io.IOException
import java.util.*


class CameraInterface private constructor() {

    private var mCamera: Camera? = null
    //默认前置摄像头
    private var mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT

    private var mIsPreviewing = false

    private var mPreviewRate = -1f

    private var mBitmapRotateAngle = 0


    fun openBackCamera() {
        openCamera(true)
    }

    fun openCamera() {
        openCamera(false)
    }

    private fun openCamera(isBackCamera: Boolean) {
        if (isBackCamera) {
            mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK
        } else {
            mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT
        }
        XLog.d("mCameraId:$mCameraId")
        //这个操作在部分设备上比较耗时，所以尽量要在线程中执行，避免在主线程中调用
        try {
            mCamera = Camera.open(mCameraId)
        } catch (e: RuntimeException) {
            XLog.e("相机已被其他应用占用，请先退出其他相机应用")
        }
    }

    fun startPreview(surfaceTexture: SurfaceTexture) {
        XLog.d()
        if (mIsPreviewing) {
            mCamera?.stopPreview()
            return
        }

        try {
            mCamera?.setPreviewTexture(surfaceTexture)
        } catch (e1: IOException) {
            e1.printStackTrace()
        }

        initCamera()
    }

    private fun initCamera() {
        val params = mCamera?.parameters!!
        //设置拍照后存储的图片格式
        params.pictureFormat = ImageFormat.JPEG

        val bestPreviewSize = getBestPreviewSize(MyApplication.mScreenWidth, MyApplication.mScreenHeight)
        XLog.d("bestPreviewSize.width:${bestPreviewSize.width},height:${bestPreviewSize.height}")
        params.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height)
        mPreviewRate = (bestPreviewSize.width / bestPreviewSize.height).toFloat()

        val bestPictureSize = getBestPictureSize(params, 640, 480)
        params.setPictureSize(bestPictureSize.width, bestPictureSize.height)

//        mCamera?.setDisplayOrientation(90)

        val focusModes = params.supportedFocusModes
        if (focusModes.contains("continuous-video")) {
            params.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO
        }
        mCamera?.parameters = params
        mCamera?.startPreview()

        mIsPreviewing = true
    }

    fun takePicture() {
        //第二个回调是返回拍照原始数据
        mCamera?.takePicture(Camera.ShutterCallback {
            //实现此回调，就能实现拍照声音功能
        }, null, Camera.PictureCallback { data, camera ->
            XLog.d("take picture success")
            var bitmap: Bitmap? = null
            if (null != data) {
                bitmap = BitmapUtil.byteArrayToBitmap(data)
                mCamera?.stopPreview()
                mIsPreviewing = false
            }

            //保存图片到sdcard
            bitmap?.let {
                XLog.d("bitmapRotateAngle:$mBitmapRotateAngle")
                val rotateBitmap = BitmapUtil.rotateBitmap(mBitmapRotateAngle, bitmap)
                BitmapUtil.saveBitmap("/sdcard/", "123.jpg", rotateBitmap)
                rotateBitmap.recycle()
            }
            //再次进入预览
            mCamera?.startPreview()
            mIsPreviewing = true

        })
    }

    private fun getBestPreviewSize(width: Int, height: Int): Camera.Size {
        val supportedPreviewSizes = mCamera?.parameters?.supportedPreviewSizes
        val widthLargerSize = ArrayList<Camera.Size>()
        if (supportedPreviewSizes != null) {
            for (item in supportedPreviewSizes) {
//                XLog.d("supportSize.width:${item.width},height:${item.height}")
                if (item.width > item.height) {
                    widthLargerSize.add(item)
                }
            }
        }
        widthLargerSize.sortWith(Comparator { lhs, rhs ->
            val offsetOne = Math.abs(lhs.width * lhs.height - width * height)
            val offsetTwo = Math.abs(rhs.width * rhs.height - width * height)
            offsetOne - offsetTwo
        })
        return widthLargerSize[0]
    }

    fun getPreviewRate(): Float {
        val size = getBestPreviewSize(MyApplication.mScreenWidth, MyApplication.mScreenHeight)
        return size.width / size.height.toFloat()
    }

    /**
     * 通过传入的宽高算出最接近于宽高值的相机大小
     */
    private fun getBestPictureSize(camPara: Camera.Parameters, width: Int, height: Int): Camera.Size {
        val allSupportedSize = camPara.supportedPictureSizes
        val widthLargerSize = ArrayList<Camera.Size>()

        for (item in allSupportedSize) {
//            XLog.d("supportSize.width:${item.width},height:${item.height}")
            if (item.width > item.height) {
                widthLargerSize.add(item)
            }
        }

        widthLargerSize.sortWith(Comparator { lhs, rhs ->
            val offsetOne = Math.abs(lhs.width * lhs.height - width * height)
            val offsetTwo = Math.abs(rhs.width * rhs.height - width * height)
            offsetOne - offsetTwo
        })

        return widthLargerSize[0]
    }

    /**
     * 获取相机的旋转角度
     */
    fun getCameraAngle(activity: Activity) : Int{
        val info = Camera.CameraInfo()
        Camera.getCameraInfo(mCameraId, info)
        //获取屏幕的旋转角度
        val rotation = activity.windowManager.defaultDisplay.rotation
        XLog.d("Activity.Rotation:$rotation")
        val degrees = when (rotation) {
            Surface.ROTATION_0 -> 0  //竖屏
            Surface.ROTATION_90 -> 90 //左横屏
            Surface.ROTATION_180 -> 180 //反向竖屏
            Surface.ROTATION_270 -> 270 //右横屏
            else -> 0
        }
        XLog.d("degress:" + degrees + ",orientation:" + info.orientation)

        var rotateAngle: Int
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            XLog.w("CAMERA_FACING_FRONT")
            rotateAngle = (info.orientation + degrees) % 360
            rotateAngle = (360 - rotateAngle) % 360 // compensate the mirror
        } else { // back-facing
            XLog.w("CAMERA_FACING_BACK")
            rotateAngle = (info.orientation - degrees + 360) % 360
        }
        XLog.d("rotateAngle:$rotateAngle")
        XLog.d("mCameraID:$mCameraId")
        if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mBitmapRotateAngle = 360 - rotateAngle
        } else {
            mBitmapRotateAngle = rotateAngle
        }
        XLog.d("mBitmapRotateAngle:$mBitmapRotateAngle")
        return rotateAngle
    }

    fun switchCamera() {
        stopCamera()
        if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            openBackCamera()
        } else {
            openCamera()
        }
    }

    fun stopCamera() {
        mIsPreviewing = false
        mCamera?.stopPreview()
        mCamera?.setPreviewCallback(null)
        mCamera?.release()
        mCamera = null
    }

    fun isPreviewing(): Boolean {
        return mIsPreviewing
    }

    fun getCamera(): Camera? {
        return mCamera
    }

    companion object {
        val instance: CameraInterface by lazy { CameraInterface() }
        var angle: Int = 0
    }

}